home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / MATH / FSULTRA1.ZIP / ULTRACOD.INC < prev    next >
Text File  |  1992-06-18  |  11KB  |  451 lines

  1. comment ! 
  2. FSU - ULTRA    The greatest random number generator that ever was
  3.         or ever will be.  Way beyond Super-Duper.
  4.         (Just kidding, but we think its a good one.)
  5.  
  6. Authors:    Arif Zaman (arif@stat.fsu.edu) and
  7.         George Marsaglia (geo@stat.fsu.edu).
  8.  
  9. Date:        27 May 1992
  10.  
  11. Version:    1.05
  12.  
  13. Copyright:    To obtain permission to incorporate this program into
  14.         any commercial product, please contact the authors at
  15.         the e-mail address given above or at
  16.  
  17.         Department of Statistics and
  18.         Supercomputer Computations Research Institute
  19.         Florida State University
  20.         Tallahassee, FL 32306.
  21.  
  22. See Also:    README        for a brief description
  23.         ULTRA.DOC    for a detailed description
  24.  
  25. -----------------------------------------------------------------------
  26. ;
  27. ; This file defines the CODE segment to be included in a main file
  28. ; see ultra.doc for details.
  29. ;
  30. cong  macro     ; Congruential generator ==============================
  31. ;
  32. ; argument in dx:ax
  33. ; result   in dx:ax = low32bits of 69069 * arg
  34. ; clobbered   bx
  35. ;
  36. ; We need the lower 32 bits of 69069 * dx:ax
  37. ; Since we only have 16 bit multiplys with 32 bit answers,
  38. ; we use long multiplication. Let (a,b) represent a*2^16 + b.
  39. ;
  40. ;            69069 =                      (  1, 3533)
  41. ;            dx:ax =                 x    ( hi, lo  )
  42. ;                                 -------------------
  43. ;                     3533 * lo =         ( a1, a2  )
  44. ;                     3533 * hi =     ( b1, b2 )
  45. ;                        1 * lo =     (  0, lo )
  46. ;                                 -------------------
  47. ;            low 32 bits of answer = (a1+b2+lo, a2  )         
  48. ;
  49.       mov  bx,ax
  50.       mov  ax,3533
  51.       mul  dx                     ; dx:ax = b1,b2 = 3533*hi
  52.       xchg bx,ax
  53.       add  bx,ax                  ; bx = b2+lo;     ax = lo;
  54.       mov  dx,3533
  55.       mul  dx                     ; dx:ax = a1,a2 = 3533*lo
  56.       add  dx,bx                  ; dx = a1+b2+lo
  57.       endm
  58.  
  59. shreg macro     ; Shift register sequence =============================
  60. ;
  61. ;  argument is dx:ax
  62. ;  result   in dx:ax
  63. ;  clobbered   bx
  64. ;
  65. ;  consider the ax register as one sign bit `as' and the rest `a..r'
  66. ;  similarly decompose dx. The operation we want to do is:
  67. ;
  68. ;          x = x xor (x shr 15);
  69. ;          x = x xor (x shl 17);
  70. ;
  71. ;  Which can be shown in terms of the decomposed registers as:
  72. ;
  73. ;     x        = ds, d..r, as, a..r
  74. ;     x shr 15 =       ds, d..r  as
  75. ;                ------------------
  76. ;     x        = ds, d..r, as, a..r
  77. ;     x shl 17 = a..r   0
  78. ;                ------------------
  79. ;
  80. ;  The above operation is equivalent to:
  81. ;
  82. ;           ax = ax xor [d..r,as]
  83. ;           dx = dx xor [a..r,ds]
  84. ;
  85.       mov  bh,ah
  86.       shl  bh,1                 ; mov as into carry
  87.       mov  bx,dx
  88.       rcl  bx,1                 ; bx = [d..r,as]
  89.       pushf                     ; save carry flag (=ds)
  90.       xor  ax,bx                ; ax = ax xor bx
  91.       popf                      ; restore the carry
  92.       mov  bx,ax
  93.       rcl  bx,1                 ; bx = [a..r,ds]
  94.       xor  dx,bx                ; dx = dx xor bx
  95.       endm
  96.  
  97. rinit proc        ; INITIALIZE SEED ARRAY =======================
  98.     Enter2arg
  99. ;
  100. ; On exit:
  101. ;    The SWBseed array is set using sign bits from the McGill
  102. ;    Super-Duper generator, which is a mix of a congruential and
  103. ;    a shift-register sequence. Flags and counters are reset.
  104. ;
  105. ; Registers Clobbered:  AX,BX,CX,DX,SI,DI.
  106. ;
  107. ; Algorithm:
  108. ;    Starting from lsm of x[0] to the msb of x[N-1], each bit is
  109. ;    formed using the sign bit of the xor of a congruential generator
  110. ;    with seed ConX and a shift register sequence with seed ShrX.
  111. ;
  112. ; Register usage
  113. ;   cx contains count for two loops
  114. ;      ch counts the outer loop (for each byte of the array x)
  115. ;      cl counts for each bit of x[i]
  116. ;   bl contains the bits until eight of them are gathered
  117. ;   es:di point to where x[i] 
  118. ;   dx:ax are used for computations
  119. ;
  120.     mov ch,N*4
  121.     mov di,offset swbseed  ; do loop for x[0], ... , x[4*n] (bytes)
  122. nextbyte:
  123.     mov bl,0        ; 8 bits of bl are made bit by bit
  124.     mov cl,8        
  125. nextbit:    push bx                     ; compute the cong and the sh-reg
  126.         mov  ax,conglo              ; generators in place
  127.         mov  dx,conghi
  128.         cong
  129.         mov  conglo,ax
  130.         mov  conghi,dx
  131.         mov  ax,shrglo
  132.         mov  dx,shrghi
  133.         shreg
  134.         mov  shrglo,ax
  135.         mov  shrghi,dx
  136.         pop  bx 
  137.  
  138.         xor  dh,byte ptr conghi+1   ; xor the top byte of arg1 and arg2
  139.         rcl  dh,1           ; move the sign bit into the carry
  140.         rcr  bl,1           ; shift it into bl
  141.     dec cl
  142.     jnz nextbit
  143.     mov al,bl
  144.     stosb               ; Store the answer in swbb[i]
  145.     dec ch
  146.     jnz nextbyte
  147. ;
  148. ; reset all counters, flags etc. and return.
  149. ;
  150.     xor bx,bx
  151.     mov swb32.c,bx
  152.     mov swb16.c,bx
  153.     mov swb8.c,bx
  154.     mov swb1.c,bx
  155.     mov flags,0
  156.     Exit2arg
  157. rinit    endp
  158.  
  159. SWBfill proc near    ; SUBTRACT-WITH-BORROW ========================
  160. ;
  161. ;  On Entry:
  162. ;     DS should point to the data segment.
  163. ;     BX contains offset to swb??.x the data array for the answer
  164. ;
  165. ;  On Exit:
  166. ;     SWBseed contains all new values computed by the SWB generator.
  167. ;     carry   contains the carry flag from the last subtraction.
  168. ;     The array pointed to by [BX] contains the seed xor'ed with
  169. ;    a congruential sequence.
  170. ;
  171. ;  Registers Clobbered: AX,BX,CX,DX,SI,DI
  172. ;
  173. ;  Algorithm:
  174. ;     The following subtractions are performed from right to left.
  175. ;     The carry propagates as though these were two long numbers,
  176. ;     with each x[i] being a `digit' in base 2^32.
  177. ;
  178. ;        x[12] ...  x[ 0]      x[36] ...  x[13]
  179. ;       -x[36] ... -x[24]     -x[23] ... -x[ 0]
  180. ;       ---------------------------------------
  181. ;        x[36] ...  x[24]      x[23] ...  x[ 0]
  182. ;
  183. ;     The x's also could be considered as pairs of base 16 digits,
  184. ;     so that x[i] is the pair y[2i+1]y[2i]. This allows us to use
  185. ;     only 16 bit subtractions with carry, perfectly suited for all
  186. ;     80x86 processors. The same idea could be extended for machines
  187. ;     with only eight bit, or even only 1 bit arithmetic.
  188. ;
  189.     EnterFill
  190.     push bx            ; Save the location for the results
  191.     mov ah,byte ptr flags   ; set carry flag to what it was the
  192.     sahf                    ; last time we exited this routine
  193.  
  194.     mov cx,24*2             ; will do first loop 48 times
  195.     mov si,offset(swbseed)+13*4; set up ds:si -> x[13]
  196.     mov di,offset(swbseed)     ; set up es:di -> x[0]
  197.  
  198. loop1:  ; On a 8086, the instructions `lodsw', `stosw' and `loop'
  199.     ; all change registers automatically as noted in parentheses
  200.  
  201.     lodsw                   ;    ax = y[i+26]     ( si = si+2 )
  202.     sbb ax,[di]             ;    ax = ax-y[i]-carry
  203.     stosw                   ;    y[i] = ax        ( di = di+2 )
  204.     loop loop1              ; loop for i=0..47    ( cx = cx-1 )
  205.  
  206.     mov cx,13*2             ; will do next loop 26 times
  207.     mov si,offset(swbseed)     ; set up ds:si -> y[0]
  208.                     ; es:di is already set up
  209. loop2:
  210.     lodsw                   ;    ax = y[i-48]     ( si = si+2 )
  211.     sbb ax,[di]             ;    ax = ax-y[i]-carry
  212.     stosw                   ;    x[i] = ax        ( di = di+2 )
  213.     loop loop2              ; loop for i=48..73   ( cx = cx-1 )
  214.  
  215.     lahf
  216.     mov byte ptr flags,ah   ; save carry flag for next time
  217. ;
  218. ; XOR the elements of x with a congruential generator and put the
  219. ; result in swbx
  220. ;
  221.     mov  si,offset(swbseed)    ; the source is the seed
  222.     pop  di            ; the destination is one of swb??.x
  223.     mov  [di-4],di        ; set swb??.p = & swb??.x[0]
  224. IFNDEF fast
  225.     mov  cx,N
  226.     mov  ax,conglo
  227.     mov  dx,conghi
  228. loopc:  cong
  229.     mov  bx,ax
  230.     lodsw
  231.     xor  ax,bx
  232.     stosw
  233.     lodsw
  234.     xor  ax,dx
  235.     stosw
  236.     mov  ax,bx
  237.     loop loopc
  238.     mov  conglo,ax
  239.     mov  conghi,dx
  240. ELSE
  241.     mov  cx,2*N
  242.     rep  movsw
  243. ENDIF
  244.     ExitFill
  245. SWBfill    endp
  246.  
  247. ; Random Number procedures ============================================
  248. ;
  249. CheckFill MACRO bits,bytes,count
  250.     local ok
  251.     dec    bits.c
  252.     jns    ok
  253.         mov   bx,offset(bits.x)
  254.         call  SWBfill
  255.         mov   bits.c,count-1
  256. ok:    mov    bx,bits.p
  257.     add    bits.p,bytes
  258. ENDM
  259.  
  260. i32bit proc
  261.     EnterProcedure
  262.     CheckFill swb32,4,N
  263.     mov    ax,[bx]
  264.     mov    dx,[bx+2]
  265.     DwordFn
  266.     ExitProcedure
  267. i32bit endp
  268.  
  269. i31bit proc
  270.     EnterProcedure
  271.     CheckFill swb32,4,N
  272.     mov    ax,[bx]
  273.     mov    dx,[bx+2]
  274.     and    dh,7Fh
  275.     DwordFn
  276.     ExitProcedure
  277. i31bit endp
  278.  
  279. i16bit proc
  280.     EnterProcedure
  281.     CheckFill swb16,2,2*N
  282.     mov    ax,[bx]
  283.     WordFn
  284.     ExitProcedure
  285. i16bit endp
  286.  
  287. i15bit proc
  288.     EnterProcedure
  289.     CheckFill swb16,2,2*N
  290.     mov    ax,[bx]
  291.     and    ah,7Fh
  292.     WordFn
  293.     ExitProcedure
  294. i15bit endp
  295.  
  296. i8bit proc
  297.     EnterProcedure
  298.     CheckFill swb8,1,4*N
  299.     mov    al,[bx]
  300.     ByteFn
  301.     ExitProcedure
  302. i8bit endp
  303.  
  304. i7bit proc
  305.     EnterProcedure
  306.     CheckFill swb8,1,4*N
  307.     mov    al,[bx]
  308.     and    al,7Fh
  309.     ByteFn
  310.     ExitProcedure
  311. i7bit endp
  312.  
  313. i1bit proc
  314.     EnterProcedure di
  315.     dec    swb1.c
  316.     jns    ok1
  317.         CheckFill  swb32,4,N    ; do an i32bit
  318.         mov   dx,[bx+2]
  319.         mov   bx,[bx]        ; with answer in dx:bx
  320.         mov   swb1.c,31
  321.         mov   di,offset(swb1.x)
  322.         mov   swb1.p,di
  323.         mov   ax,ds
  324.         mov   es,ax
  325.  
  326.         mov   cx,16
  327. stosb1:        mov   al,1
  328.         and   al,bl
  329.         stosb
  330.         shr   bx,1
  331.         loop  stosb1
  332.  
  333.         mov      cl,16
  334. stosb2:        mov   al,1
  335.         and   al,dl
  336.         stosb
  337.         shr   dx,1
  338.         loop  stosb2
  339. ok1:    mov    bx,swb1.p
  340.     inc    swb1.p
  341.     mov    al,[bx]
  342.     ByteFn
  343.     ExitProcedure di
  344. i1bit endp
  345.  
  346. uni proc
  347.     EnterProcedure
  348.     fild    neg31
  349.     CheckFill  swb32,4,N
  350.     and    byte ptr [bx+3],7Fh
  351.     jnz    oku
  352.         mov      ax,[bx]
  353.         mov   tmpw3,ax
  354.         mov      ax,[bx+2]
  355.         mov      tmpw4,ax
  356.         CheckFill  swb32,4,N
  357.         mov      ax,[bx]
  358.         mov   tmpw1,ax
  359.         mov      ax,[bx]
  360.         mov   tmpw2,ax
  361.         fild  tmpq
  362.         jmp   uxit
  363. oku:    fild    dword ptr [bx]
  364. uxit:    fscale            ; scale the integer by the exponent
  365.     fstp st(1)        ; dump the exponent from the fpp
  366.     RealFn
  367.     ExitProcedure
  368. uni endp
  369.  
  370. vni proc
  371.     EnterProcedure
  372.     fild    neg31
  373.     CheckFill  swb32,4,N
  374.     test    byte ptr [bx+3],0FFh
  375.     jnz    okv
  376.         mov      ax,[bx]
  377.         mov   tmpw3,ax
  378.         mov   ax,[bx+2]
  379.         mov   tmpw4,ax
  380.         CheckFill  swb32,4,N
  381.         mov   ax,[bx]
  382.         mov   tmpw1,ax
  383.         mov   ax,[bx+2]
  384.         mov   tmpw2,ax
  385.         fild  tmpq
  386.         jmp   vxit
  387. okv:    fild    dword ptr [bx]
  388. vxit:    fscale            ; scale the integer by the exponent
  389.     fstp    st(1)        ; dump the exponent from the fpp
  390.     RealFn
  391.     ExitProcedure
  392. vni endp
  393.  
  394. duni proc
  395.     EnterProcedure
  396.     fild    neg63
  397.     CheckFill  swb32,4,N
  398.     dec    swb32.c
  399.     jns    okdu
  400.         mov      ax,[bx]
  401.         mov   tmpw1,ax
  402.         mov      ax,[bx+2]
  403.         mov   tmpw2,ax
  404.         mov   bx,offset(swb32.x)
  405.         call  SWBfill
  406.         mov   swb32.c,N-1
  407.         mov   ax,word ptr swb32.x
  408.         mov   tmpw3,ax
  409.         mov   ax,word ptr swb32.x+2
  410.         mov   tmpw4,ax
  411.         and   byte ptr [tmpq+7],7Fh
  412.         fild  tmpq
  413.         jmp   duxit
  414. okdu:    and    byte ptr [bx+7],7Fh
  415.     fild    qword ptr [bx]
  416. duxit:    add    swb32.p,4
  417.     fscale
  418.     fstp    st(1)
  419.     DoubleFn
  420.     ExitProcedure
  421. duni endp
  422.  
  423. dvni proc
  424.     EnterProcedure
  425.     fild    neg63
  426.     CheckFill  swb32,4,N
  427.     dec    swb32.c
  428.     jns    okdv
  429.         mov   ax,[bx]
  430.         mov   tmpw1,ax
  431.         mov   ax,[bx+2]
  432.         mov   tmpw2,ax
  433.         mov   bx,offset(swb32.x)
  434.         call  SWBfill
  435.         mov   swb32.c,N-1
  436.         mov   ax,word ptr swb32.x
  437.         mov   tmpw3,ax
  438.         mov   ax,word ptr swb32.x+2
  439.         mov   tmpw4,ax
  440.         fild  tmpq
  441.         jmp   dvxit
  442. okdv:    fild    qword ptr [bx]
  443. dvxit:    add    swb32.p,4
  444.     fscale
  445.     fstp    st(1)
  446.     DoubleFn
  447.     ExitProcedure
  448. dvni endp
  449.  
  450.